El curso ofrecido por el Instituto Nacional de Estadísticas de Chile (INE) se centra en la importancia de manejar y analizar datos faltantes, que son una realidad en cualquier análisis de datos del mundo real. Los valores faltantes pueden aparecer por diversas razones, desde problemas de medición hasta problemas de calidad de los datos, y su presencia puede dificultar la comprensión y la interpretación de los análisis.
En este contexto, el curso del INE brinda a los participantes las habilidades y herramientas necesarias para manejar los datos faltantes de manera efectiva y mejorar la calidad de sus análisis. En particular, se utiliza el paquete R de naniar, una herramienta muy útil para explorar, visualizar y manejar valores faltantes en R.
El curso consta de varios capítulos, cada uno enfocado en un aspecto específico del manejo de datos faltantes. En el primer capítulo se aprende a detectar, contar y resumir la falta de datos, utilizando técnicas como la función is.na() y las funciones de resumen como sum(), mean(), entre otras. Además, se enseña cómo explorar los patrones de datos faltantes en diferentes variables y casos, y cómo detectar posibles sesgos y patrones subyacentes en los datos.
En los capítulos siguientes, se aborda la imputación de valores faltantes, es decir, cómo llenar los vacíos en los datos utilizando diferentes técnicas de imputación, como la imputación por media, la imputación múltiple y la regresión de los valores faltantes. También se aprende a evaluar la calidad de los datos imputados y a tomar decisiones basadas en estos conjuntos de datos imputados.
Además, el curso incluye una sección dedicada a la visualización de datos faltantes, donde se aprende a producir visualizaciones generales para todo el conjunto de datos y para las variables, casos y otros resúmenes, y cómo explorar estos en los grupos.
En resumen, el curso del INE proporciona las habilidades y herramientas necesarias para manejar, explorar y analizar datos faltantes de manera efectiva y mejorar la calidad de los análisis de datos del mundo real.
#Capitulo 1
Introducción a los datos faltantes Para este curso se utilizarán herramientas como tidyverse y el paquete R de naniar para enseñar a manejar y analizar datos faltantes de manera efectiva. El paquete naniar es una herramienta muy útil para explorar, visualizar y manejar valores faltantes en R.
Introducción La estadística Gertrude Mary Cox dijo una vez: “Lo mejor que se puede hacer con los datos faltantes es no tener ninguno”. Si bien esto es cierto, no es el mundo en el que vivimos. Trabajar con datos del mundo real significa trabajar con datos faltantes. Para ser un gran analista, necesitas saber cómo lidiar con los valores faltantes. Comprender cómo funcionan los datos faltantes es importante, ya que pueden tener efectos inesperados en tu análisis. Por ejemplo, ajustar un modelo lineal en datos con valores faltantes elimina fragmentos de datos. Esto significa que tus decisiones no se basan en la evidencia correcta. Reemplazar los valores faltantes, lo que se llama imputación, debe hacerse con mucho cuidado, ya que insertar solo la media puede llevar a estimaciones y decisiones deficientes.
¿Qué aprenderás? En este curso aprenderás sobre qué son los valores faltantes, cómo encontrar datos faltantes, cómo manipular y limpiar datos faltantes, por qué faltan datos y cómo imputar valores faltantes.
Conocimientos previos Para este curso, asumiré que tienes experiencia básica a intermedia con R, experiencia en la creación de gráficos utilizando ggplot2, experiencia en el uso de dplyr para manipular datos y experiencia en ajustar modelos lineales en R. En este primer capítulo, presentamos los valores faltantes y cómo verificarlos y contarlos.
¿Qué son los valores faltantes? Antes de comenzar, debemos definir los valores faltantes. Los valores faltantes son valores que deberían haberse registrado, pero no lo fueron. Piensa en esto de esta manera: puedes no haber registrado accidentalmente que viste un pájaro, esto es un valor faltante. Esto es diferente a registrar que no se observaron pájaros. R almacena los valores faltantes como NA, que significa no disponible.
¿Cómo puedo verificar si tengo valores faltantes? Los valores faltantes no saltan y gritan “¡Estoy aquí!”. Por lo general, están ocultos, como una aguja en un pajar. Para detectar valores faltantes, usa any_na, que devuelve TRUE si hay valores faltantes y FALSE si no los hay. are_na pregunta “¿son estos NA?” y devuelve TRUE/FALSE para cada valor. are_na nos muestra 3 valores TRUE, que corresponden a 3 valores faltantes. Para evitar contar cada TRUE manualmente, n_miss cuenta el número de valores faltantes. Y prop_miss proporciona la proporción de valores faltantes, lo que proporciona un contexto importante: ¡el 50% de los datos está faltando!
Trabajando con datos faltantes ¿Qué sucede cuando mezclamos valores faltantes con nuestros cálculos? Necesitamos saber qué sucede para poder estar preparados para encontrar estos casos. La regla general es: Los cálculos con NA devuelven NA. Digamos que tienes la altura de tres amigos: Sophie, Dan y Fred. La suma de sus alturas devuelve NA, esto se debe a que no conocemos la suma de un número y NA.
Trampas con datos faltantes Hay algunas “trampas” que debes tener en cuenta al trabajar con datos faltantes: Por ejemplo, NaN significa “Not a Number” (No es un número) y se obtiene de operaciones como la raíz cuadrada de -1. R interpreta NaN como un valor faltante. NULL es un valor vacío pero no es faltante. Esto es sutilmente diferente de los valores faltantes: un cubo vacío no tiene agua faltante. Inf es un valor infinito, y se obtiene de ecuaciones como 10 dividido por 0 y no es faltante.
Trampas con datos faltantes (2) Por último, ten cuidado con las declaraciones condicionales con valores faltantes. Por ejemplo, NA o TRUE es TRUE. NA o FALSE es NA. NA + NaN es NA. NaN + NA es NaN.
¡Practiquemos! ¡Practiquemos!
##Usando y encontrando valores faltantes
Al trabajar con datos faltantes, hay algunos comandos con los que deberías estar familiarizado - en primer lugar, debes poder identificar si hay valores faltantes y dónde se encuentran.
Usando las herramientas any_na() y are_na(), identifica qué valores faltan.
# Create x, a vector, with values NA, NaN, Inf, ".", and "missing"
x <- c(NA, NaN,Inf, ".", "missing")
# Use any_na() and are_na() on to explore the missings
any_na(x)
## [1] TRUE
are_na(x)
## [1] TRUE FALSE FALSE FALSE FALSE
###¿Cuántos valores faltantes hay?
Una de las primeras cosas que desearás comprobar en un nuevo conjunto de datos es si existen valores faltantes y cuántos hay.
Podrías usar are_na() y contar los valores faltantes, pero la forma más eficiente de contarlos es usar la función n_miss(). Esto te dirá el número total de valores faltantes en los datos.
Luego puedes encontrar el porcentaje de valores faltantes en los datos con la función pct_miss. Esto te dirá el porcentaje de valores faltantes en los datos.
También puedes encontrar el complemento de estos valores, cuántos valores completos hay, usando n_complete y pct_complete.
# Using the example dataframe of heights and weights dat_hw
dat_hw <- read.table("~/edi_imp/datacamp_JB/dealing/dat_hw.txt", h=T, dec=".")
# Use n_miss() to count the total number of missing values in dat_hw
naniar::n_miss(dat_hw)
## [1] 30
# Use n_miss() on dat_hw$weight to count the total number of missing values
naniar::n_miss(dat_hw$weight)
## [1] 15
# Use n_complete() on dat_hw to count the total number of complete values
n_complete(dat_hw)
## [1] 170
# Use n_complete() on dat_hw$weight to count the total number of complete values
n_complete(dat_hw$weight)
## [1] 85
# Use prop_miss() and prop_complete() on dat_hw to count the total number of missing values in each of the variables
prop_miss(dat_hw)
## [1] 0.15
prop_complete(dat_hw)
## [1] 0.85
###Resumiendo la ausencia de datos
Ahora que comprendes el comportamiento de los valores faltantes en R y cómo contarlos, escalaremos nuestros resúmenes para casos (filas) y variables, utilizando miss_var_summary() y miss_case_summary(), y también exploraremos cómo se pueden aplicar a grupos en un dataframe utilizando la función group_by de dplyr.
# Summarise missingness in each variable of the `airquality` dataset
miss_var_summary(airquality)
## # A tibble: 6 × 3
## variable n_miss pct_miss
## <chr> <int> <dbl>
## 1 Ozone 37 24.2
## 2 Solar.R 7 4.58
## 3 Wind 0 0
## 4 Temp 0 0
## 5 Month 0 0
## 6 Day 0 0
# Summarise missingness in each case of the `airquality` dataset
miss_case_summary(airquality)
## # A tibble: 153 × 3
## case n_miss pct_miss
## <int> <int> <dbl>
## 1 5 2 33.3
## 2 27 2 33.3
## 3 6 1 16.7
## 4 10 1 16.7
## 5 11 1 16.7
## 6 25 1 16.7
## 7 26 1 16.7
## 8 32 1 16.7
## 9 33 1 16.7
## 10 34 1 16.7
## # … with 143 more rows
# Return the summary of missingness in each variable, grouped by Month, in the `airquality` dataset
airquality %>% group_by(Month) %>% miss_var_summary()
## # A tibble: 25 × 4
## # Groups: Month [5]
## Month variable n_miss pct_miss
## <int> <chr> <int> <dbl>
## 1 5 Ozone 5 16.1
## 2 5 Solar.R 4 12.9
## 3 5 Wind 0 0
## 4 5 Temp 0 0
## 5 5 Day 0 0
## 6 6 Ozone 21 70
## 7 6 Solar.R 0 0
## 8 6 Wind 0 0
## 9 6 Temp 0 0
## 10 6 Day 0 0
## # … with 15 more rows
# Return the summary of missingness in each case, grouped by Month, in the `airquality` dataset
airquality %>% group_by(Month) %>% miss_case_summary()
## # A tibble: 153 × 4
## # Groups: Month [5]
## Month case n_miss pct_miss
## <int> <int> <int> <dbl>
## 1 5 5 2 40
## 2 5 27 2 40
## 3 5 6 1 20
## 4 5 10 1 20
## 5 5 11 1 20
## 6 5 25 1 20
## 7 5 26 1 20
## 8 5 1 0 0
## 9 5 2 0 0
## 10 5 3 0 0
## # … with 143 more rows
###Tabulando los valores faltantes
Las sumarizaciones de los valores faltantes que acabamos de calcular nos dan el número y el porcentaje de observaciones faltantes para los casos y variables.
Otra manera de resumir los valores faltantes es mediante la tabulación del número de veces que hay 0, 1, 2, 3, valores faltantes en una variable o en un caso.
En este ejercicio, vamos a tabular el número de valores faltantes en cada caso y variable utilizando miss_var_table() y miss_case_table(), y también combinaremos estos resúmenes con el operador group_by de dplyr para explorar los resúmenes sobre una variable de agrupación en el conjunto de datos.
# Tabulate missingness in each variable and case of the `airquality` dataset
miss_case_table(airquality)
## # A tibble: 3 × 3
## n_miss_in_case n_cases pct_cases
## <int> <int> <dbl>
## 1 0 111 72.5
## 2 1 40 26.1
## 3 2 2 1.31
miss_var_table(airquality)
## # A tibble: 3 × 3
## n_miss_in_var n_vars pct_vars
## <int> <int> <dbl>
## 1 0 4 66.7
## 2 7 1 16.7
## 3 37 1 16.7
# Tabulate the missingness in each variable, grouped by Month, in the `airquality` dataset
airquality %>% group_by(Month) %>% miss_var_table()
## # A tibble: 12 × 4
## # Groups: Month [5]
## Month n_miss_in_var n_vars pct_vars
## <int> <int> <int> <dbl>
## 1 5 0 3 60
## 2 5 4 1 20
## 3 5 5 1 20
## 4 6 0 4 80
## 5 6 21 1 20
## 6 7 0 4 80
## 7 7 5 1 20
## 8 8 0 3 60
## 9 8 3 1 20
## 10 8 5 1 20
## 11 9 0 4 80
## 12 9 1 1 20
# Tabulate of missingness in each case, grouped by Month, in the `airquality` dataset
airquality %>% group_by(Month) %>% miss_case_table()
## # A tibble: 11 × 4
## # Groups: Month [5]
## Month n_miss_in_case n_cases pct_cases
## <int> <int> <int> <dbl>
## 1 5 0 24 77.4
## 2 5 1 5 16.1
## 3 5 2 2 6.45
## 4 6 0 9 30
## 5 6 1 21 70
## 6 7 0 26 83.9
## 7 7 1 5 16.1
## 8 8 0 23 74.2
## 9 8 1 8 25.8
## 10 9 0 29 96.7
## 11 9 1 1 3.33
###Otros resúmenes de valores faltantes
Algunos resúmenes de valores faltantes son particularmente útiles para diferentes tipos de datos. Por ejemplo, miss_var_span() y miss_var_run().
miss_var_span() calcula el número de valores faltantes en una variable especificada para un intervalo repetido. Esto es muy útil en datos de series de tiempo, para buscar patrones de valores faltantes semanales (de 7 días).
miss_var_run() calcula el número de “rachas” o “cadenas” de valores faltantes. Esto es útil para encontrar patrones inusuales de valores faltantes, por ejemplo, podría encontrar un patrón repetitivo de 5 completos y 5 faltantes.
Tanto miss_var_span() como miss_var_run() funcionan con el operador group_by de dplyr.
# Calculate the summaries for each run of missingness for the variable, hourly_counts
miss_var_run(pedestrian, var = hourly_counts)
## # A tibble: 35 × 2
## run_length is_na
## <int> <chr>
## 1 6628 complete
## 2 1 missing
## 3 5250 complete
## 4 624 missing
## 5 3652 complete
## 6 1 missing
## 7 1290 complete
## 8 744 missing
## 9 7420 complete
## 10 1 missing
## # … with 25 more rows
# Calculate the summaries for each span of missingness, for a span of 4000, for the variable hourly_counts
miss_var_span(pedestrian, var = hourly_counts, span_every = 4000)
## # A tibble: 10 × 6
## span_counter n_miss n_complete prop_miss prop_complete n_in_span
## <int> <int> <int> <dbl> <dbl> <int>
## 1 1 0 4000 0 1 4000
## 2 2 1 3999 0.00025 1.00 4000
## 3 3 121 3879 0.0302 0.970 4000
## 4 4 503 3497 0.126 0.874 4000
## 5 5 745 3255 0.186 0.814 4000
## 6 6 0 4000 0 1 4000
## 7 7 1 3999 0.00025 1.00 4000
## 8 8 0 4000 0 1 4000
## 9 9 745 3255 0.186 0.814 4000
## 10 10 432 1268 0.254 0.746 1700
# For each `month` variable, calculate the run of missingness for hourly_counts
pedestrian %>% group_by(month) %>% miss_var_run(var = hourly_counts)
## # A tibble: 51 × 3
## # Groups: month [12]
## month run_length is_na
## <ord> <int> <chr>
## 1 January 2976 complete
## 2 February 2784 complete
## 3 March 2976 complete
## 4 April 888 complete
## 5 April 552 missing
## 6 April 1440 complete
## 7 May 744 complete
## 8 May 72 missing
## 9 May 2160 complete
## 10 June 2880 complete
## # … with 41 more rows
# For each `month` variable, calculate the span of missingness of a span of 2000, for the variable hourly_counts
pedestrian %>% group_by(month) %>% miss_var_span(var = hourly_counts, span_every = 2000)
## # A tibble: 25 × 7
## # Groups: month [12]
## month span_counter n_miss n_complete prop_miss prop_complete n_in_span
## <ord> <int> <int> <int> <dbl> <dbl> <int>
## 1 January 1 0 2000 0 1 2000
## 2 January 2 0 976 0 1 976
## 3 February 1 0 2000 0 1 2000
## 4 February 2 0 784 0 1 784
## 5 March 1 0 2000 0 1 2000
## 6 March 2 0 976 0 1 976
## 7 April 1 552 1448 0.276 0.724 2000
## 8 April 2 0 880 0 1 880
## 9 May 1 72 1928 0.036 0.964 2000
## 10 May 2 0 976 0 1 976
## # … with 15 more rows
###Sus primeras visualizaciones de datos faltantes
Puede resultar difícil determinar dónde están los valores faltantes en sus datos, y aquí es donde la visualización realmente puede ayudar.
La función vis_miss() crea una visualización general de la falta de datos en los datos. También tiene opciones para agrupar filas según la falta de datos, usando cluster = TRUE; así como opciones para ordenar las columnas, desde las más faltantes hasta las menos faltantes (sort_miss = TRUE).
# Visualize all of the missingness in the `riskfactors` dataset
vis_miss(riskfactors)
## Warning: `gather_()` was deprecated in tidyr 1.2.0.
## Please use `gather()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.
# Visualize and cluster all of the missingness in the `riskfactors` dataset
vis_miss(riskfactors, cluster = TRUE)
# visualise and sort the columns by missingness in the `riskfactors` dataset
vis_miss(riskfactors, sort_miss = TRUE)
###Visualización de casos y variables faltantes
Para obtener una imagen clara de los valores faltantes en las variables y casos, utiliza gg_miss_var() y gg_miss_case(). Estas son las versiones visuales de miss_var_summary() y miss_case_summary().
Estos pueden dividirse en múltiples gráficos, uno para cada categoría, eligiendo una variable para segmentar por ella.
# Visualize the number of missings in cases using `gg_miss_case()`
gg_miss_case(riskfactors)
# Explore the number of missings in cases using `gg_miss_case()` and facet by the variable `education`
gg_miss_case(riskfactors, facet = education)
# Visualize the number of missings in variables using `gg_miss_var()`
gg_miss_var(riskfactors)
## Warning: It is deprecated to specify `guide = FALSE` to remove a guide. Please
## use `guide = "none"` instead.
# Explore the number of missings in variables using `gg_miss_var()` and facet by the variable `education`
gg_miss_var(riskfactors, facet = education)
## Warning: It is deprecated to specify `guide = FALSE` to remove a guide. Please
## use `guide = "none"` instead.
##Visualizando patrones de datos faltantes
Practiquemos algunas formas diferentes de visualizar patrones de datos faltantes usando:
gg_miss_upset() para mostrar un patrón general de datos faltantes. gg_miss_fct() para un conjunto de datos que tiene un factor de interés: el matrimonio. y gg_miss_span() para explorar los datos faltantes en un conjunto de datos de series de tiempo. ¿Qué notas sobre los datos faltantes y la segmentación en los datos?
# Using the airquality dataset, explore the missingness pattern using gg_miss_upset()
gg_miss_upset(airquality)
# With the riskfactors dataset, explore how the missingness changes across the marital variable using gg_miss_fct()
gg_miss_fct(x = riskfactors, fct = marital)
# Using the pedestrian dataset, explore how the missingness of hourly_counts changes over a span of 3000
gg_miss_span(pedestrian, var = hourly_counts, span_every = 3000)
# Using the pedestrian dataset, explore the impact of month by facetting by month
# and explore how missingness changes for a span of 1000
gg_miss_span(pedestrian, var = hourly_counts , span_every = 1000, facet = month)
#Limpieza y organización de valores faltantes
En el capítulo dos, aprenderás cómo descubrir valores faltantes ocultos como “missing” o “N/A” y reemplazarlos con NA. Aprenderás cómo manejar de manera eficiente los valores faltantes implícitos: aquellos valores que se dan por sentados como faltantes pero que no se enumeran explícitamente. También cubriremos cómo explorar la dependencia de datos faltantes, discutiendo Missing Completely at Random (MCAR), Missing At Random (MAR), Missing Not At Random (MNAR) y lo que significan para el análisis de tus datos.
##Búsqueda y reemplazo de valores faltantes
###Usando miss_scan_count
Tienes un conjunto de datos con valores faltantes codificados como "N/A", "missing" y "na". Pero antes de seguir adelante y comenzar a reemplazarlos con NA, deberíamos tener una idea de qué tan grande es el problema.
Utiliza miss_scan_count para contar los valores faltantes posibles en el conjunto de datos pacman, que contiene tres columnas:
year: el año en que la persona obtuvo esa puntuación. initial: las iniciales de la persona. score: las puntuaciones de esa persona.
# Using the example dataframe
pacman<-readRDS("~/edi_imp/datacamp_JB/dealing/pacman.rds")
# Explore the strange missing values "N/A"
miss_scan_count(data = pacman, search = list("N/A"))
## # A tibble: 6 × 2
## Variable n
## <chr> <int>
## 1 year 0
## 2 month 0
## 3 day 0
## 4 initial 0
## 5 score 100
## 6 country 0
# Explore the strange missing values "missing"
miss_scan_count(data = pacman, search = list("missing"))
## # A tibble: 6 × 2
## Variable n
## <chr> <int>
## 1 year 93
## 2 month 93
## 3 day 93
## 4 initial 0
## 5 score 0
## 6 country 0
# Explore the strange missing values "na"
miss_scan_count(data = pacman, search = list("na"))
## # A tibble: 6 × 2
## Variable n
## <chr> <int>
## 1 year 100
## 2 month 100
## 3 day 100
## 4 initial 0
## 5 score 0
## 6 country 0
# Explore the strange missing values " " (a single space)
miss_scan_count(data = pacman, search = list(" "))
## # A tibble: 6 × 2
## Variable n
## <chr> <int>
## 1 year 0
## 2 month 0
## 3 day 0
## 4 initial 0
## 5 score 0
## 6 country 100
# Explore all of the strange missing values, "N/A", "missing", "na", " "
miss_scan_count(data = pacman, search = list("N/A", "missing","na", " "))
## # A tibble: 6 × 2
## Variable n
## <chr> <int>
## 1 year 193
## 2 month 193
## 3 day 193
## 4 initial 0
## 5 score 100
## 6 country 100
###Usando replace_with_na
Siguiendo con el conjunto de datos anterior, ahora sabemos que tenemos algunos valores faltantes extraños.
Ahora, vamos a hacer algo al respecto y reemplazar estos valores con valores faltantes (por ejemplo, NA) usando la función replace_with_na().
# Print the top of the pacman data using `head()`
head(pacman)
## # A tibble: 6 × 6
## year month day initial score country
## <chr> <chr> <chr> <chr> <chr> <chr>
## 1 2007 10 27 LEX 2065812 "CA"
## 2 1995 8 23 PNY 1163465 "JP"
## 3 1980 2 8 MBJ 175380 " "
## 4 1982 5 9 QRC 2025632 "ES"
## 5 na na na YPZ 925357 "NZ"
## 6 2013 11 15 RVJ 319733 "AU"
# Replace the strange missing values "N/A", "na", and
# "missing" with `NA` for the variables, year, and score
pacman_clean <- replace_with_na(pacman, replace = list(year = c("N/A", "na", "missing"),
score = c("N/A", "na", "missing")))
# Test if `pacman_clean` still has these values in it?
miss_scan_count(pacman_clean, search = list("N/A", "na", "missing"))
## # A tibble: 6 × 2
## Variable n
## <chr> <int>
## 1 year 0
## 2 month 193
## 3 day 193
## 4 initial 0
## 5 score 0
## 6 country 0
###Usando las variantes “scoped” de replace_with_na
Para reducir la repetición de código al reemplazar valores con NA, utiliza las variantes “scoped” de replace_with_na():
replace_with_na_at() replace_with_na_if() replace_with_na_all()
La sintaxis de reemplazo se ve así:
~.x == "N/A" Esto reemplaza todos los casos que son iguales a "N/A".
~.x %in% c("N/A", "missing", "na", " ") Reemplaza todos los casos que tienen "N/A", "missing", "na" o " ".
# Use `replace_with_na_at()` to replace with NA
replace_with_na_at(pacman,
.vars = c("year", "month", "day"),
~.x %in% c("N/A", "missing", "na", " "))
## # A tibble: 2,000 × 6
## year month day initial score country
## <chr> <chr> <chr> <chr> <chr> <chr>
## 1 2007 10 27 LEX 2065812 "CA"
## 2 1995 8 23 PNY 1163465 "JP"
## 3 1980 2 8 MBJ 175380 " "
## 4 1982 5 9 QRC 2025632 "ES"
## 5 <NA> <NA> <NA> YPZ 925357 "NZ"
## 6 2013 11 15 RVJ 319733 "AU"
## 7 2003 12 4 VKD 3322668 "US"
## 8 2016 9 9 ZIS 2137806 "CN"
## 9 2013 3 20 IYD 3059716 "CN"
## 10 1993 5 19 CHQ 231892 "AU"
## # … with 1,990 more rows
# Use `replace_with_na_if()` to replace with NA the character values using `is.character`
replace_with_na_if(pacman,
.predicate = is.character,
~.x %in% c("N/A", "missing", "na", " "))
## # A tibble: 2,000 × 6
## year month day initial score country
## <chr> <chr> <chr> <chr> <chr> <chr>
## 1 2007 10 27 LEX 2065812 CA
## 2 1995 8 23 PNY 1163465 JP
## 3 1980 2 8 MBJ 175380 <NA>
## 4 1982 5 9 QRC 2025632 ES
## 5 <NA> <NA> <NA> YPZ 925357 NZ
## 6 2013 11 15 RVJ 319733 AU
## 7 2003 12 4 VKD 3322668 US
## 8 2016 9 9 ZIS 2137806 CN
## 9 2013 3 20 IYD 3059716 CN
## 10 1993 5 19 CHQ 231892 AU
## # … with 1,990 more rows
# Use `replace_with_na_all()` to replace with NA
replace_with_na_all(pacman, ~.x %in% c("N/A", "missing", "na", " "))
## # A tibble: 2,000 × 6
## year month day initial score country
## <chr> <chr> <chr> <chr> <chr> <chr>
## 1 2007 10 27 LEX 2065812 CA
## 2 1995 8 23 PNY 1163465 JP
## 3 1980 2 8 MBJ 175380 <NA>
## 4 1982 5 9 QRC 2025632 ES
## 5 <NA> <NA> <NA> YPZ 925357 NZ
## 6 2013 11 15 RVJ 319733 AU
## 7 2003 12 4 VKD 3322668 US
## 8 2016 9 9 ZIS 2137806 CN
## 9 2013 3 20 IYD 3059716 CN
## 10 1993 5 19 CHQ 231892 AU
## # … with 1,990 more rows
##Rellenando valores faltantes hacia abajo (cap2_s2)
###Arreglando valores faltantes implícitos usando complete()
Vamos a explorar un nuevo conjunto de datos, frogger.
Este conjunto de datos contiene 4 puntuaciones por jugador registradas en diferentes momentos: morning, afternoon, evening y late_night.
Cada jugador debería haber jugado 4 partidas, una en cada uno de estos momentos, pero parece que no todos los jugadores completaron todos estos juegos.
Utiliza la función complete() para hacer explícitos estos valores faltantes implícitos.
frogger <- read_excel("~/edi_imp/datacamp_JB/dealing/frogger.xlsx")
# Print the frogger data to have a look at it
frogger
## # A tibble: 15 × 3
## name time value
## <chr> <chr> <chr>
## 1 jesse morning 6678
## 2 jesse afternoon 800060
## 3 jesse evening 475528
## 4 jesse late_night 143533
## 5 andy morning 425115
## 6 andy afternoon 587468
## 7 andy late_night 111000
## 8 nic afternoon 588532
## 9 nic late_night 915533
## 10 dan morning 388148
## 11 dan evening 180912
## 12 alex morning 552670
## 13 alex afternoon 98355
## 14 alex evening 266055
## 15 alex late_night 121056
# Use `complete()` on the `time` and `name` variables to
# make implicit missing values explicit
frogger_tidy <- frogger %>% complete(time, name)
###Arreglando valores faltantes explícitos usando fill()
Un tipo de valor faltante que puede ser obvio de tratar es donde se da la primera entrada de un grupo, pero las entradas subsiguientes están marcadas como NA.
Estos valores faltantes a menudo son el resultado de valores vacíos en hojas de cálculo para evitar ingresar múltiples nombres varias veces; así como para “legibilidad humana”.
Este tipo de problema se puede resolver utilizando la función fill() del paquete tidyr.
# Print the frogger data to have a look at it
frogger
## # A tibble: 15 × 3
## name time value
## <chr> <chr> <chr>
## 1 jesse morning 6678
## 2 jesse afternoon 800060
## 3 jesse evening 475528
## 4 jesse late_night 143533
## 5 andy morning 425115
## 6 andy afternoon 587468
## 7 andy late_night 111000
## 8 nic afternoon 588532
## 9 nic late_night 915533
## 10 dan morning 388148
## 11 dan evening 180912
## 12 alex morning 552670
## 13 alex afternoon 98355
## 14 alex evening 266055
## 15 alex late_night 121056
# Use `fill()` to fill down the name variable in the frogger dataset
frogger %>% fill(name)
## # A tibble: 15 × 3
## name time value
## <chr> <chr> <chr>
## 1 jesse morning 6678
## 2 jesse afternoon 800060
## 3 jesse evening 475528
## 4 jesse late_night 143533
## 5 andy morning 425115
## 6 andy afternoon 587468
## 7 andy late_night 111000
## 8 nic afternoon 588532
## 9 nic late_night 915533
## 10 dan morning 388148
## 11 dan evening 180912
## 12 alex morning 552670
## 13 alex afternoon 98355
## 14 alex evening 266055
## 15 alex late_night 121056
###Usando complete() y fill() juntos
¡Ahora pongámoslo todo junto!
Utiliza complete() y fill() juntos para corregir valores faltantes explícitos e implícitos en el conjunto de datos frogger.
# Print the frogger data to have a look at it
frogger
## # A tibble: 15 × 3
## name time value
## <chr> <chr> <chr>
## 1 jesse morning 6678
## 2 jesse afternoon 800060
## 3 jesse evening 475528
## 4 jesse late_night 143533
## 5 andy morning 425115
## 6 andy afternoon 587468
## 7 andy late_night 111000
## 8 nic afternoon 588532
## 9 nic late_night 915533
## 10 dan morning 388148
## 11 dan evening 180912
## 12 alex morning 552670
## 13 alex afternoon 98355
## 14 alex evening 266055
## 15 alex late_night 121056
# Correctly fill() and complete() missing values so that our dataset becomes sensible
frogger %>%
fill(name) %>%
complete(name, time)
## # A tibble: 20 × 3
## name time value
## <chr> <chr> <chr>
## 1 alex afternoon 98355
## 2 alex evening 266055
## 3 alex late_night 121056
## 4 alex morning 552670
## 5 andy afternoon 587468
## 6 andy evening <NA>
## 7 andy late_night 111000
## 8 andy morning 425115
## 9 dan afternoon <NA>
## 10 dan evening 180912
## 11 dan late_night <NA>
## 12 dan morning 388148
## 13 jesse afternoon 800060
## 14 jesse evening 475528
## 15 jesse late_night 143533
## 16 jesse morning 6678
## 17 nic afternoon 588532
## 18 nic evening <NA>
## 19 nic late_night 915533
## 20 nic morning <NA>
##Dependencia de datos faltantes
###Diferencias entre MCAR y MAR
Necesitamos hacer ciertas suposiciones sobre nuestros datos cuando avanzamos en el análisis.
¿Cuál de las siguientes respuestas sobre MCAR y MAR es VERDADERA?
##Posibles respuestas
En general, eliminar observaciones es más seguro para datos MCAR que eliminar observaciones para datos MAR.
MCAR significa que la falta de datos está relacionada con los datos observados, mientras que para MAR, la falta de datos está relacionada con los datos no observados.
MAR y MCAR son efectivamente lo mismo, la distinción no es importante.
Los datos MCAR no están relacionados con los datos observados y no observados. Los datos MAR están relacionados con los datos observados.
###Explorando la dependencia de datos faltantes
Para aprender sobre la estructura de la falta de datos en los datos, puedes explorar cómo cambia la presentación de la falta de datos al ordenar los datos.
Para el conjunto de datos oceanbuoys, explora la falta de datos con vis_miss() y luego ordénalo por algunas variables diferentes.
Este no es un proceso definitivo, pero te ayudará a comenzar a hacer las preguntas correctas sobre tus datos. Exploramos técnicas más poderosas en el próximo capítulo.
# Arrange by year
oceanbuoys %>% arrange(year) %>% vis_miss()
# Arrange by latitude
oceanbuoys %>% arrange(latitude) %>% vis_miss()
# Arrange by wind_ew (wind east west)
oceanbuoys %>% arrange(wind_ew) %>% vis_miss()
###Explorando aún más la dependencia de los datos faltantes
Usando la información previa sobre el conjunto de datos oceanbuoys, ¿cuál de estas afirmaciones es la más apropiada sobre el tipo de datos faltantes?
Intenta usar gg_miss_var() y gg_miss_case(), agrupando por año para obtener más información. Por ejemplo:
library(naniar) gg_miss_var(oceanbuoys, facet = year)
Posibles respuestas:
Los datos son MCAR: la dirección del viento es importante para explicar los datos faltantes.
Los datos son MCAR: el año es importante para explicar los datos faltantes.
Los datos son MAR: la ubicación no es importante para explicar los datos faltantes.
Los datos son MAR: tanto el año como la ubicación son importantes para explicar los datos faltantes.
#Capítulo 2
##Herramientas para explorar la dependencia de los datos faltantes
###Creando datos de matriz de sombra
Los datos faltantes pueden ser complicados de pensar, ya que normalmente no se proclaman por sí mismos y en su lugar se esconden entre la maleza de los datos.
Una forma de ayudar a exponer los valores faltantes es cambiar la forma en que pensamos sobre los datos, pensando en cada valor de datos como faltante o no faltante.
La función as_shadow() en R transforma un dataframe en una matriz de sombra, un formato de datos especial donde los valores son o bien faltantes (NA) o no faltantes (!NA).
Los nombres de columna de una matriz de sombra son los mismos que los datos, pero tienen un sufijo agregado _NA.
Para realizar un seguimiento y comparar los valores de los datos con su estado de falta, use la función bind_shadow(). Tener los datos en este formato, con la columna de matriz de sombra unida a los datos regulares, se llama datos nabular.
# Create shadow matrix data with `as_shadow()`
as_shadow(oceanbuoys)
## # A tibble: 736 × 8
## year_NA latitude_NA longitude_NA sea_temp_c…¹ air_t…² humid…³ wind_…⁴ wind_…⁵
## <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct>
## 1 !NA !NA !NA !NA !NA !NA !NA !NA
## 2 !NA !NA !NA !NA !NA !NA !NA !NA
## 3 !NA !NA !NA !NA !NA !NA !NA !NA
## 4 !NA !NA !NA !NA !NA !NA !NA !NA
## 5 !NA !NA !NA !NA !NA !NA !NA !NA
## 6 !NA !NA !NA !NA !NA !NA !NA !NA
## 7 !NA !NA !NA !NA !NA !NA !NA !NA
## 8 !NA !NA !NA !NA !NA !NA !NA !NA
## 9 !NA !NA !NA !NA !NA !NA !NA !NA
## 10 !NA !NA !NA !NA !NA !NA !NA !NA
## # … with 726 more rows, and abbreviated variable names ¹sea_temp_c_NA,
## # ²air_temp_c_NA, ³humidity_NA, ⁴wind_ew_NA, ⁵wind_ns_NA
# Create nabular data by binding the shadow to the data with `bind_shadow()`
bind_shadow(oceanbuoys)
## # A tibble: 736 × 16
## year latit…¹ longi…² sea_t…³ air_t…⁴ humid…⁵ wind_ew wind_ns year_NA latit…⁶
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <fct> <fct>
## 1 1997 0 -110 27.6 27.1 79.6 -6.40 5.40 !NA !NA
## 2 1997 0 -110 27.5 27.0 75.8 -5.30 5.30 !NA !NA
## 3 1997 0 -110 27.6 27 76.5 -5.10 4.5 !NA !NA
## 4 1997 0 -110 27.6 26.9 76.2 -4.90 2.5 !NA !NA
## 5 1997 0 -110 27.6 26.8 76.4 -3.5 4.10 !NA !NA
## 6 1997 0 -110 27.8 26.9 76.7 -4.40 1.60 !NA !NA
## 7 1997 0 -110 28.0 27.0 76.5 -2 3.5 !NA !NA
## 8 1997 0 -110 28.0 27.1 78.3 -3.70 4.5 !NA !NA
## 9 1997 0 -110 28.0 27.2 78.6 -4.20 5 !NA !NA
## 10 1997 0 -110 28.0 27.2 76.9 -3.60 3.5 !NA !NA
## # … with 726 more rows, 6 more variables: longitude_NA <fct>,
## # sea_temp_c_NA <fct>, air_temp_c_NA <fct>, humidity_NA <fct>,
## # wind_ew_NA <fct>, wind_ns_NA <fct>, and abbreviated variable names
## # ¹latitude, ²longitude, ³sea_temp_c, ⁴air_temp_c, ⁵humidity, ⁶latitude_NA
# Bind only the variables with missing values by using bind_shadow(only_miss = TRUE)
bind_shadow(oceanbuoys, only_miss = TRUE)
## # A tibble: 736 × 11
## year latit…¹ longi…² sea_t…³ air_t…⁴ humid…⁵ wind_ew wind_ns sea_t…⁶ air_t…⁷
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <fct> <fct>
## 1 1997 0 -110 27.6 27.1 79.6 -6.40 5.40 !NA !NA
## 2 1997 0 -110 27.5 27.0 75.8 -5.30 5.30 !NA !NA
## 3 1997 0 -110 27.6 27 76.5 -5.10 4.5 !NA !NA
## 4 1997 0 -110 27.6 26.9 76.2 -4.90 2.5 !NA !NA
## 5 1997 0 -110 27.6 26.8 76.4 -3.5 4.10 !NA !NA
## 6 1997 0 -110 27.8 26.9 76.7 -4.40 1.60 !NA !NA
## 7 1997 0 -110 28.0 27.0 76.5 -2 3.5 !NA !NA
## 8 1997 0 -110 28.0 27.1 78.3 -3.70 4.5 !NA !NA
## 9 1997 0 -110 28.0 27.2 78.6 -4.20 5 !NA !NA
## 10 1997 0 -110 28.0 27.2 76.9 -3.60 3.5 !NA !NA
## # … with 726 more rows, 1 more variable: humidity_NA <fct>, and abbreviated
## # variable names ¹latitude, ²longitude, ³sea_temp_c, ⁴air_temp_c, ⁵humidity,
## # ⁶sea_temp_c_NA, ⁷air_temp_c_NA
###Realizando resúmenes agrupados de valores faltantes
Ahora que puedes crear datos nabulares, vamos a utilizarlos para explorar los datos. Vamos a calcular estadísticas de resumen basadas en los valores faltantes de otra variable.
Para hacer esto, vamos a seguir los siguientes pasos:
Primero, bind_shadow() convierte los datos en datos nabulares.
A continuación, realiza algunos resúmenes en los datos utilizando group_by() y summarize() para calcular la media y la desviación estándar, utilizando las funciones mean() y sd().
# `bind_shadow()` and `group_by()` humidity missingness (`humidity_NA`)
oceanbuoys %>%
bind_shadow() %>%
group_by(humidity_NA) %>%
summarize(wind_ew_mean = mean(wind_ew), # calculate mean of wind_ew
wind_ew_sd = sd(wind_ew)) # calculate standard deviation of wind_ew
## # A tibble: 2 × 3
## humidity_NA wind_ew_mean wind_ew_sd
## <fct> <dbl> <dbl>
## 1 !NA -3.78 1.90
## 2 NA -3.30 2.31
# Repeat this, but calculating summaries for wind north south (`wind_ns`)
oceanbuoys %>%
bind_shadow() %>%
group_by(humidity_NA) %>%
summarize(wind_ns_mean = mean(wind_ns),
wind_ns_sd = sd(wind_ns))
## # A tibble: 2 × 3
## humidity_NA wind_ns_mean wind_ns_sd
## <fct> <dbl> <dbl>
## 1 !NA 2.78 2.06
## 2 NA 1.66 2.23
##Explorando combinaciones adicionales de valores faltantes
Puede ser útil obtener un poco de información adicional sobre el número de casos en cada condición de valores faltantes.
En este ejercicio, vamos a añadir información sobre el número de casos observados utilizando n() dentro de la función summarize().
Luego añadiremos un nivel adicional de agrupamiento al examinar la combinación de humedad faltante (humidity_NA) y temperatura del aire faltante (air_temp_c_NA).
# Summarize wind_ew by the missingness of `air_temp_c_NA`
oceanbuoys %>%
bind_shadow() %>%
group_by(air_temp_c_NA) %>%
summarize(wind_ew_mean = mean(wind_ew),
wind_ew_sd = sd(wind_ew),
n_obs = n())
## # A tibble: 2 × 4
## air_temp_c_NA wind_ew_mean wind_ew_sd n_obs
## <fct> <dbl> <dbl> <int>
## 1 !NA -3.91 1.85 655
## 2 NA -2.17 2.14 81
# Summarize wind_ew by missingness of `air_temp_c_NA` and `humidity_NA`
oceanbuoys %>%
bind_shadow() %>%
group_by(air_temp_c_NA, humidity_NA) %>%
summarize(wind_ew_mean = mean(wind_ew),
wind_ew_sd = sd(wind_ew),
n_obs = n())
## `summarise()` has grouped output by 'air_temp_c_NA'. You can override using the
## `.groups` argument.
## # A tibble: 4 × 5
## # Groups: air_temp_c_NA [2]
## air_temp_c_NA humidity_NA wind_ew_mean wind_ew_sd n_obs
## <fct> <fct> <dbl> <dbl> <int>
## 1 !NA !NA -4.01 1.74 565
## 2 !NA NA -3.24 2.31 90
## 3 NA !NA -2.06 2.08 78
## 4 NA NA -4.97 1.74 3
##Visualizando los valores faltantes de una variable
###Datos nabulares y llenado por valores faltantes
Los estadísticos de resumen son útiles para calcular, pero como dicen, una imagen vale más que mil palabras.
En este ejercicio, vamos a explorar cómo puedes utilizar datos nabular para explorar la variación en una variable según los valores faltantes de otra.
Vamos a utilizar el conjunto de datos oceanbuoys de naniar.
# First explore the missingness structure of `oceanbuoys` using `vis_miss()`
vis_miss(oceanbuoys)
# Explore the distribution of `wind_ew` for the missingness
# of `air_temp_c_NA` using `geom_density()`
bind_shadow(oceanbuoys) %>%
ggplot(aes(x = wind_ew,
color = air_temp_c_NA)) +
geom_density()
# Explore the distribution of sea temperature for the
# missingness of humidity (humidity_NA) using `geom_density()`
bind_shadow(oceanbuoys) %>%
ggplot(aes(x = sea_temp_c,
color = humidity_NA)) +
geom_density()
## Warning: Removed 3 rows containing non-finite values (stat_density).
Ahora puedes utilizar datos nabulares para visualizar y explorar datos faltantes utilizando gráficos de densidad.
###Datos nabulares y resumen por valores faltantes
En este ejercicio, vamos a explorar cómo utilizar datos nabular para explorar la variación en una variable según los valores faltantes de otra.
Vamos a utilizar el conjunto de datos oceanbuoys de naniar, y luego crear múltiples gráficos de los datos utilizando facetas.
Esto te permite explorar diferentes capas de valores faltantes.
# Explore the distribution of wind east west (wind_ew) for the missingness of air temperature
# using geom_density() and faceting by the missingness of air temperature (air_temp_c_NA).
oceanbuoys %>%
bind_shadow() %>%
ggplot(aes(x = wind_ew)) +
geom_density() +
facet_wrap(~air_temp_c_NA)
# Build upon this visualization by filling by the missingness of humidity (humidity_NA).
oceanbuoys %>%
bind_shadow() %>%
ggplot(aes(x = wind_ew,
color = humidity_NA)) +
geom_density() +
facet_wrap(~air_temp_c_NA)
Ahora puedes utilizar datos nabulares para visualizar y explorar datos faltantes.
###Explorar variación por valores faltantes: gráficos de caja
Los ejercicios anteriores utilizan datos nabular junto con gráficos de densidad para explorar la variación en una variable según los valores faltantes de otra.
Vamos a utilizar el conjunto de datos oceanbuoys de naniar, utilizando gráficos de caja en lugar de facetas u otros para explorar diferentes capas de valores faltantes.
# Explore the distribution of wind east west (`wind_ew`) for
# the missingness of air temperature using `geom_boxplot()`
oceanbuoys %>%
bind_shadow() %>%
ggplot(aes(x = air_temp_c_NA,
y = wind_ew)) +
geom_boxplot()
# Build upon this visualization by faceting by the missingness of humidity (`humidity_NA`).
oceanbuoys %>%
bind_shadow() %>%
ggplot(aes(x = air_temp_c_NA,
y = wind_ew)) +
geom_boxplot() +
facet_wrap(~humidity_NA)
Ahora puedes utilizar datos nabulares para visualizar y explorar datos faltantes con gráficos de caja y envolturas de facetas.
##Visualizar valores faltantes en dos variables
###Explorando datos faltantes con gráficos de dispersión
Los valores faltantes en un gráfico de dispersión en ggplot2 se eliminan por defecto, con una advertencia.
Podemos mostrar los valores faltantes en un gráfico de dispersión utilizando geom_miss_point() - una geometría especial de ggplot2 que desplaza los valores faltantes dentro del gráfico, mostrándolos un 10% por debajo del mínimo de la variable.
Practiquemos esta visualización con el conjunto de datos oceanbuoys.
# Explore the missingness in wind and air temperature, and
# display the missingness using `geom_miss_point()`
ggplot(oceanbuoys,
aes(x = wind_ew,
y = air_temp_c)) +
geom_miss_point()
# Explore the missingness in humidity and air temperature,
# and display the missingness using `geom_miss_point()`
ggplot(oceanbuoys,
aes(x = humidity,
y = air_temp_c)) +
geom_miss_point()
###Usando facetas para explorar valores faltantes
Debido a que geom_miss_point() es una geometría de ggplot, puedes usarla con características de ggplot2 como el uso de facetas.
Esto significa que podemos explorar rápidamente los valores faltantes y permanecer dentro de los límites familiares de ggplot2.
# Explore the missingness in wind and air temperature, and display the
# missingness using `geom_miss_point()`. Facet by year to explore this further.
ggplot(oceanbuoys,
aes(x = wind_ew,
y = air_temp_c)) +
geom_miss_point() +
facet_wrap(~year)
# Explore the missingness in humidity and air temperature, and display the
# missingness using `geom_miss_point()` Facet by year to explore this further.
ggplot(oceanbuoys,
aes(x = humidity,
y = air_temp_c)) +
geom_miss_point() +
facet_wrap(~year)
Ahora puedes usar geom_miss_point() para explorar valores faltantes en un gráfico de dispersión y puedes usar facetas para expandir y explorar aún más.
###Facetas para explorar valores faltantes (múltiples gráficos) Otra técnica útil con geom_miss_point() es explorar los valores faltantes creando múltiples gráficos.
Así como lo hemos hecho en ejercicios anteriores, podemos usar los datos nabulares para ayudarnos a crear gráficos facetados adicionales.
Incluso podemos crear múltiples gráficos facetados según los valores en los datos, como el año, y las características de los datos, como la falta de valores.
# Use geom_miss_point() and facet_wrap to explore how the missingness
# in wind_ew and air_temp_c is different for missingness of humidity
bind_shadow(oceanbuoys) %>%
ggplot(aes(x = wind_ew,
y = air_temp_c)) +
geom_miss_point() +
facet_wrap(~humidity_NA)
# Use geom_miss_point() and facet_grid to explore how the missingness in wind_ew and air_temp_c
# is different for missingness of humidity AND by year - by using `facet_grid(humidity_NA ~ year)`
bind_shadow(oceanbuoys) %>%
ggplot(aes(x = wind_ew,
y = air_temp_c)) +
geom_miss_point() +
facet_grid(humidity_NA~year)
##Realizando y rastreando imputaciones.
###Imputar datos por debajo del rango con datos nulos. Queremos hacer un seguimiento de los valores que imputamos. Si no lo hacemos, es muy difícil evaluar qué tan buenos son los valores imputados.
Vamos a practicar imputando datos y recreando visualizaciones en el conjunto de ejercicios anterior mediante la imputación de valores por debajo del rango de los datos.
Esta es una forma muy útil de ayudar a explorar aún más la falta de datos y también proporciona el marco para imputar valores faltantes.
Primero, vamos a imputar los datos por debajo del rango usando impute_below_all(), y luego visualizar los datos. Notamos que aunque podemos ver dónde están los valores faltantes en este caso, necesitamos alguna forma de hacer un seguimiento de ellos. El patrón de programación de seguimiento de datos faltantes puede ayudar con esto.
# Impute the data below the range using `impute_below`.
ocean_imp <- impute_below_all(oceanbuoys)
# Visualize the new missing values
ggplot(ocean_imp,
aes(x = wind_ew, y = air_temp_c)) +
geom_point()
# Impute and track data with `bind_shadow`, `impute_below`, and `add_label_shadow`
ocean_imp_track <- bind_shadow(oceanbuoys) %>%
impute_below_all() %>%
add_label_shadow()
# Look at the imputed values
ocean_imp_track
## # A tibble: 736 × 17
## year latit…¹ longi…² sea_t…³ air_t…⁴ humid…⁵ wind_ew wind_ns year_NA latit…⁶
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <fct> <fct>
## 1 1997 0 -110 27.6 27.1 79.6 -6.40 5.40 !NA !NA
## 2 1997 0 -110 27.5 27.0 75.8 -5.30 5.30 !NA !NA
## 3 1997 0 -110 27.6 27 76.5 -5.10 4.5 !NA !NA
## 4 1997 0 -110 27.6 26.9 76.2 -4.90 2.5 !NA !NA
## 5 1997 0 -110 27.6 26.8 76.4 -3.5 4.10 !NA !NA
## 6 1997 0 -110 27.8 26.9 76.7 -4.40 1.60 !NA !NA
## 7 1997 0 -110 28.0 27.0 76.5 -2 3.5 !NA !NA
## 8 1997 0 -110 28.0 27.1 78.3 -3.70 4.5 !NA !NA
## 9 1997 0 -110 28.0 27.2 78.6 -4.20 5 !NA !NA
## 10 1997 0 -110 28.0 27.2 76.9 -3.60 3.5 !NA !NA
## # … with 726 more rows, 7 more variables: longitude_NA <fct>,
## # sea_temp_c_NA <fct>, air_temp_c_NA <fct>, humidity_NA <fct>,
## # wind_ew_NA <fct>, wind_ns_NA <fct>, any_missing <chr>, and abbreviated
## # variable names ¹latitude, ²longitude, ³sea_temp_c, ⁴air_temp_c, ⁵humidity,
## # ⁶latitude_NA
###Visualizar valores imputados en un gráfico de dispersión.
Ahora, vamos a recrear uno de los gráficos anteriores que vimos en el capítulo tres que utilizaba geom_miss_point().
Para hacer esto, necesitamos imputar los datos por debajo del rango de los datos. Esta es una imputación especial para explorar los datos. Esta imputación ilustrará lo que necesitamos practicar: cómo hacer un seguimiento de los valores faltantes. Para imputar los datos por debajo del rango de los datos, usamos la función impute_below_all().
# Impute and track the missing values
ocean_imp_track <- bind_shadow(oceanbuoys) %>%
impute_below_all() %>%
add_label_shadow()
# Visualize the missingness in wind and air temperature,
# coloring missing air temp values with air_temp_c_NA
ggplot(ocean_imp_track,
aes(x = wind_ew, y = air_temp_c, color = air_temp_c_NA)) +
geom_point()
# Visualize humidity and air temp, coloring any missing cases using the variable any_missing
ggplot(ocean_imp_track,
aes(x = humidity, y = air_temp_c, color = any_missing)) +
geom_point()
###Crear un histograma de los datos imputados.
Ahora que podemos recrear la primera visualización de geom_miss_point(), vamos a explorar cómo podemos aplicar esto a otras tareas exploratorias.
Una tarea útil es evaluar el número de valores faltantes en una variable dada usando un histograma. Podemos hacer esto usando el conjunto de datos ocean_imp_track que creamos en el último ejercicio, el cual está cargado en esta sesión.
# Explore the values of air_temp_c, visualizing the amount of missings with `air_temp_c_NA`.
p <- ggplot(ocean_imp_track, aes(x = air_temp_c, fill = air_temp_c_NA)) + geom_histogram()
# Expore the missings in humidity using humidity_NA
p2 <- ggplot(ocean_imp_track, aes(x = humidity, fill = humidity_NA)) + geom_histogram()
# Explore the missings in air_temp_c according to year, using `facet_wrap(~year)`.
p + facet_wrap(~year)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
# Explore the missings in humidity according to year, using `facet_wrap(~year)`.
p2 + facet_wrap(~year)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
###Evaluando imputaciones malas.
Para evaluar imputaciones, es útil saber cómo se ve algo malo. Para explorar esto, veamos un método de imputación típicamente malo: imputar usando el valor promedio.
En este ejercicio vamos a explorar cómo funciona el método de imputación de promedio usando un diagrama de caja, utilizando el conjunto de datos oceanbuoys.
# Impute the mean value and track the imputations
ocean_imp_mean <- bind_shadow(oceanbuoys) %>%
impute_mean_all() %>%
add_label_shadow()
# Explore the mean values in humidity in the imputed dataset
ggplot(ocean_imp_mean,
aes(x = humidity_NA, y = humidity)) +
geom_boxplot()
# Explore the values in air temperature in the imputed dataset
ggplot(ocean_imp_mean,
aes(x = air_temp_c_NA, y = air_temp_c)) +
geom_boxplot()
### Evaluating imputations: The scale
Si bien la imputación de la media puede no parecer tan mala cuando la comparamos mediante un diagrama de caja, es importante tener una idea de la variación en los datos. Es por eso que es importante explorar cómo cambia la escala y la dispersión de los valores imputados en comparación con los datos.
Una forma de evaluar la adecuación de la escala de las imputaciones es usar un gráfico de dispersión para explorar si los valores son apropiados o no.
# Explore imputations in air temperature and humidity,
# coloring by the variable, any_missing
ggplot(ocean_imp_mean,
aes(x = air_temp_c, y = humidity, color = any_missing)) +
geom_point()
# Explore imputations in air temperature and humidity,
# coloring by the variable, any_missing, and faceting by year
ggplot(ocean_imp_mean,
aes(x = air_temp_c, y = humidity, color = any_missing)) +
geom_point() +
facet_wrap(~year)
###Evaluando imputaciones: en muchas variables.
Hasta ahora, hemos cubierto formas de ver las variables individuales o pares de variables y sus valores imputados. Sin embargo, a veces deseamos ver las imputaciones para muchas variables. Para hacer esto, es necesario realizar algún tratamiento de datos y reorganización. Esta lección cubre cómo realizar este procesamiento de datos, que puede ser un poco complicado cuando se considera su uso en datos nabular. La función shadow_long() coloca los datos en la forma adecuada para este tipo de visualizaciones.
# Gather the imputed data
ocean_imp_mean_gather <- shadow_long(ocean_imp_mean,
humidity,
air_temp_c)
# Inspect the data
ocean_imp_mean_gather
## # A tibble: 1,472 × 4
## variable value variable_NA value_NA
## <chr> <chr> <chr> <chr>
## 1 air_temp_c 27.14999962 air_temp_c_NA !NA
## 2 air_temp_c 27.02000046 air_temp_c_NA !NA
## 3 air_temp_c 27 air_temp_c_NA !NA
## 4 air_temp_c 26.93000031 air_temp_c_NA !NA
## 5 air_temp_c 26.84000015 air_temp_c_NA !NA
## 6 air_temp_c 26.94000053 air_temp_c_NA !NA
## 7 air_temp_c 27.04000092 air_temp_c_NA !NA
## 8 air_temp_c 27.11000061 air_temp_c_NA !NA
## 9 air_temp_c 27.20999908 air_temp_c_NA !NA
## 10 air_temp_c 27.25 air_temp_c_NA !NA
## # … with 1,462 more rows
ocean_imp_mean_gather$value<-as.numeric(ocean_imp_mean_gather$value)
# Explore the imputations in a histogram
ggplot(ocean_imp_mean_gather,
aes(x = value, fill = value_NA)) +
geom_histogram() +
facet_wrap(~variable)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
###Utilizando simputation para imputar datos.
Existen muchos paquetes de imputación en R. Nos enfocaremos en usar el paquete simputation, que proporciona una interfaz simple y potente para realizar imputaciones.
Construir un buen modelo de imputación es muy importante, pero es un tema complejo: hay tanto para construir un buen modelo de imputación como para construir un buen modelo estadístico. En este curso, nos enfocaremos en cómo evaluar las imputaciones.
Primero, vamos a ver cómo utilizar la función impute_lm(), que imputa valores de acuerdo a un modelo lineal especificado.
En este ejercicio, vamos a aplicar las técnicas de evaluación anteriores a los datos con impute_lm(), y luego construir sobre este método de imputación en lecciones posteriores.
library(simputation)
##
## Attaching package: 'simputation'
## The following object is masked from 'package:naniar':
##
## impute_median
# Impute humidity and air temperature using wind_ew and wind_ns, and track missing values
ocean_imp_lm_wind <- oceanbuoys %>%
bind_shadow() %>%
impute_lm(air_temp_c ~ wind_ew + wind_ns) %>%
impute_lm(humidity ~ wind_ew + wind_ns) %>%
add_label_shadow()
# Plot the imputed values for air_temp_c and humidity, colored by missingness
ggplot(ocean_imp_lm_wind,
aes(x = air_temp_c, y = humidity, color = any_missing)) +
geom_point()
### Evaluando y comparando imputaciones
Cuando se construye un modelo de imputación, es una buena idea compararlo con otro método. En esta lección, vamos a comparar el conjunto de datos previamente imputados creado utilizando impute_lm() con el conjunto de datos imputados con la media. Ambos conjuntos de datos están incluidos en este ejercicio como ocean_imp_lm_wind y ocean_imp_mean, respectivamente.
# Bind the models together
bound_models <- bind_rows(mean = ocean_imp_mean,
lm_wind = ocean_imp_lm_wind,
.id = "imp_model")
# Inspect the values of air_temp and humidity as a scatter plot
ggplot(bound_models,
aes(x = air_temp_c,
y = humidity,
color = any_missing)) +
geom_point() +
facet_wrap(~imp_model)
### Evaluando imputaciones (muchos modelos y variables)
Cuando se construye un modelo de imputación, es una buena idea compararlo con otro método.
En esta lección, se te pedirá que agregues un modelo de imputación final que contenga una pieza adicional de información útil que ayude a explicar parte de la variación en los datos. Luego, compararás los valores, como se hizo anteriormente en la última lección.
# Build a model adding year to the outcome
ocean_imp_lm_wind_year <- bind_shadow(oceanbuoys) %>%
impute_lm(air_temp_c ~ wind_ew + wind_ns + year) %>%
impute_lm(humidity ~ wind_ew + wind_ns + year) %>%
add_label_shadow()
# Bind the mean, lm_wind, and lm_wind_year models together
bound_models <- bind_rows(mean = ocean_imp_mean,
lm_wind = ocean_imp_lm_wind,
lm_wind_year = ocean_imp_lm_wind_year,
.id = "imp_model")
# Explore air_temp and humidity, coloring by any missings, and faceting by imputation model
ggplot(bound_models, aes(x = air_temp_c, y = humidity, color = any_missing)) +
geom_point() + facet_wrap(~imp_model)
###Combinación y comparación de muchos modelos de imputación
Para evaluar los diferentes métodos de imputación, necesitamos ponerlos en un único dataframe. A continuación, compararás tres enfoques diferentes para manejar los datos faltantes utilizando el conjunto de datos oceanbuoys.
El primer método es utilizar solo los casos completados y se carga como ocean_cc. El segundo método es imputar valores utilizando un modelo lineal con predicciones hechas con wind y se carga como ocean_imp_lm_wind. Crearás el tercer conjunto de datos imputados, ocean_imp_lm_all, utilizando un modelo lineal e imputando las variables sea_temp_c, air_temp_c y humidity utilizando las variables wind_ew, wind_ns, year, latitude y longitude.
Luego unirás todos los conjuntos de datos (ocean_cc, ocean_imp_lm_wind y ocean_imp_lm_all), llamándolo bound_models.
ocean_cc<-oceanbuoys %>%
na.omit() %>%
bind_shadow %>%
add_label_shadow()
# Create an imputed dataset using a linear models
ocean_imp_lm_all <- bind_shadow(oceanbuoys) %>%
add_label_shadow() %>%
impute_lm(sea_temp_c ~ wind_ew + wind_ns + year + latitude + longitude) %>%
impute_lm(air_temp_c ~ wind_ew + wind_ns + year + latitude + longitude) %>%
impute_lm(humidity ~ wind_ew + wind_ns + year + latitude + longitude)
# Bind the datasets
bound_models <- bind_rows(cc = ocean_cc,
imp_lm_wind = ocean_imp_lm_wind,
imp_lm_all = ocean_imp_lm_all,
.id = "imp_model")
# Look at the models
bound_models
## # A tibble: 2,037 × 18
## imp_m…¹ year latit…² longi…³ sea_t…⁴ air_t…⁵ humid…⁶ wind_ew wind_ns year_NA
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <fct>
## 1 cc 1997 0 -110 27.6 27.1 79.6 -6.40 5.40 !NA
## 2 cc 1997 0 -110 27.5 27.0 75.8 -5.30 5.30 !NA
## 3 cc 1997 0 -110 27.6 27 76.5 -5.10 4.5 !NA
## 4 cc 1997 0 -110 27.6 26.9 76.2 -4.90 2.5 !NA
## 5 cc 1997 0 -110 27.6 26.8 76.4 -3.5 4.10 !NA
## 6 cc 1997 0 -110 27.8 26.9 76.7 -4.40 1.60 !NA
## 7 cc 1997 0 -110 28.0 27.0 76.5 -2 3.5 !NA
## 8 cc 1997 0 -110 28.0 27.1 78.3 -3.70 4.5 !NA
## 9 cc 1997 0 -110 28.0 27.2 78.6 -4.20 5 !NA
## 10 cc 1997 0 -110 28.0 27.2 76.9 -3.60 3.5 !NA
## # … with 2,027 more rows, 8 more variables: latitude_NA <fct>,
## # longitude_NA <fct>, sea_temp_c_NA <fct>, air_temp_c_NA <fct>,
## # humidity_NA <fct>, wind_ew_NA <fct>, wind_ns_NA <fct>, any_missing <chr>,
## # and abbreviated variable names ¹imp_model, ²latitude, ³longitude,
## # ⁴sea_temp_c, ⁵air_temp_c, ⁶humidity
stamos imputando nuestros datos por una razón: ¡queremos analizar los datos!
En este ejemplo, estamos interesados en predecir la temperatura del mar, así que vamos a construir un modelo lineal que prediga la temperatura del mar.
Ajustaremos este modelo a cada uno de los conjuntos de datos que creamos y luego exploraremos los coeficientes en los datos.
Los objetos de la lección anterior (ocean_cc, ocean_imp_lm_wind, ocean_imp_lm_all y bound_models) se cargan en el espacio de trabajo.
# Create the model summary for each dataset
model_summary <- bound_models %>%
group_by(imp_model) %>%
nest() %>%
mutate(mod = purrr::map(data, ~lm(sea_temp_c ~ air_temp_c + humidity + year, data = .)),
res = purrr::map(mod, residuals),
pred = purrr::map(mod, predict),
tidy = purrr::map(mod, broom::tidy))
# Explore the coefficients in the model
model_summary %>%
select(imp_model,tidy) %>%
unnest()
## Warning: `cols` is now required when using unnest().
## Please use `cols = c(tidy)`
## # A tibble: 12 × 6
## # Groups: imp_model [3]
## imp_model term estimate std.error statistic p.value
## <chr> <chr> <dbl> <dbl> <dbl> <dbl>
## 1 cc (Intercept) -735. 45.9 -16.0 8.19e- 48
## 2 cc air_temp_c 0.864 0.0231 37.4 2.64e-154
## 3 cc humidity 0.0341 0.00390 8.74 2.69e- 17
## 4 cc year 0.369 0.0232 15.9 3.46e- 47
## 5 imp_lm_wind (Intercept) -1742. 56.1 -31.0 1.83e-135
## 6 imp_lm_wind air_temp_c 0.365 0.0279 13.1 2.73e- 35
## 7 imp_lm_wind humidity 0.0225 0.00690 3.26 1.17e- 3
## 8 imp_lm_wind year 0.880 0.0283 31.1 6.79e-136
## 9 imp_lm_all (Intercept) -697. 51.8 -13.5 5.04e- 37
## 10 imp_lm_all air_temp_c 0.890 0.0255 35.0 2.90e-158
## 11 imp_lm_all humidity 0.0127 0.00463 2.75 6.03e- 3
## 12 imp_lm_all year 0.351 0.0262 13.4 1.12e- 36
best_model <- "imp_lm_all"